package com.yanqu.road.server.gameplayer.module.activity.jieshi;

import com.alibaba.fastjson.JSON;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.jieshi.*;
import com.yanqu.road.entity.activity.jieshi.config.*;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.activity.jieshi.eJieShiPositionType;
import com.yanqu.road.entity.enums.activity.jieshi.eJieShiShopType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.*;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.logic.bussiness.activity.JieShiActivityBusiness;
import com.yanqu.road.logic.helper.CalcPowerResult;
import com.yanqu.road.logic.helper.PowerHelper;
import com.yanqu.road.pb.activity.JieShiProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.logic.activity.condition.jieshi.JieShiJiaoZiRankParam;
import com.yanqu.road.server.manger.ForbiddenWordMgr;
import com.yanqu.road.server.manger.MultipleLanguageMgr;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.jieshi.JieShiMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.system.CommonMgr;
import com.yanqu.road.server.pb.JieShiPb;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.config.Config;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 灯火街市
 */
public class JieShiModule extends GeneralModule {

    private RandomHelper randomHelper = new RandomHelper();
    private JieShiUserData userData;

    public JieShiModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        JieShiConfig config = JieShiMgr.getConfig();
        if (config != null && ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            userData = JieShiActivityBusiness.getJieShiUserData(config.getActivityInfo().getActivityId(), player.getUserId());
        }
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (userData != null) {
            if (userData.isInsertOption()) {
                JieShiActivityBusiness.addJieShiUserData(userData);
            } else if (userData.isUpdateOption()) {
                JieShiActivityBusiness.updateJieShiUserData(userData);
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {
        initUserData();
        // 同步数据
        syncData();
    }

    public void initSystem() {
        initUserData();
        // 同步数据
        syncData();
    }

    /**
     * 初始化用户数据
     */
    private synchronized void initUserData() {
        // 系统未解锁
        if (!SystemOpenMgr.systemOpen(player, eSystemId.JieShi.getValue())) {
            return;
        }

        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null || !ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            return;
        }
        if (userData != null && config.getActivityInfo().getActivityId() == userData.getActivityId()) {
            return;
        }
        JieShiUserData jieShiUserData = new JieShiUserData();
        jieShiUserData.setActivityId(config.getActivityInfo().getActivityId());
        jieShiUserData.setUserId(player.getUserId());
        jieShiUserData.setJieShiLevel(1);
        // 初始时辰 0-11
        jieShiUserData.setHour(config.getLIGHTMARKET_MAP_BEGIN_TIME() - 1);

        // 添加默认人偶
        jieShiUserData.setDollId(config.getLIGHTMARKET_DOY_DEFAULT_ITEM_ID());
        List<JieShiDollData> dollList = new ArrayList<>();
        JieShiDollData userDoll = new JieShiDollData(config.getLIGHTMARKET_DOY_DEFAULT_ITEM_ID(), 0);
        dollList.add(userDoll);
        jieShiUserData.setDollList(dollList);

        jieShiUserData.setBuffList(new ArrayList<>());
        jieShiUserData.setEnergy(config.getLIGHTMARKET_ENERGY_MAX_NUM());
        jieShiUserData.setLastEnergyRecTime(System.currentTimeMillis());
        jieShiUserData.setMapId(config.getLIGHTMARKET_MAP_ID_CHOOSE());
        jieShiUserData.setMapBuildList(new ArrayList<>());
        // 已解锁的地块
        jieShiUserData.setUnlockPosition(new ArrayList<>());
        jieShiUserData.setRuffianList(new ArrayList<>());
        jieShiUserData.setEventList(new ArrayList<>());
        jieShiUserData.setJieDaoSiLevel(1);
        jieShiUserData.setJiaoZi(0);
        jieShiUserData.setScore(0);
        jieShiUserData.setPatronsDataList(new ArrayList<>());
        jieShiUserData.setAttack(0);
        jieShiUserData.setTravelTimes(0);
        jieShiUserData.setGuide(false);
        // 随机一个名字
        String key = "LIGHTMARKET_MAIN_NAME_" + randomHelper.next(1, config.getLIGHTMARKET_NAME_NUM() + 1);
        jieShiUserData.setNickName(MultipleLanguageMgr.getContent(key, player.getLanguage()));
        jieShiUserData.setInsertOption();
        userData = jieShiUserData;
        // 街市等级成就
        player.notifyListener(eGamePlayerEventType.JieShiLevel.getValue(), BigInteger.valueOf(userData.getJieShiLevel()));
    }

    /**
     * 门客能力变更
     */
    public void patronsAbilityChange(List<UserPatrons> patronsList) {
        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null) {
            return;
        }
        ActivityInfo activityInfo = config.getActivityInfo();
        if (!ActivityMgr.activityInTime(activityInfo)) {
            return;
        }
        if (userData == null) {
            return;
        }
        List<Integer> patronsIdList = new ArrayList<>();
        for (UserPatrons userPatrons : patronsList) {
            patronsIdList.add(userPatrons.getPatronsId());
        }
        boolean needUpdate = false;
        for (JieShiPatronsData patronsData : userData.getPatronsDataList()) {
            if (patronsIdList.contains(patronsData.getPatronsId())) {
                needUpdate = true;
                break;
            }
        }
        if (needUpdate) {
            updatePatronsAttack();
        }

    }

    /**
     * 更新门客武力值及自己的总武力
     * 有变动或者门客更新
     */
    public void updatePatronsAttack() {
        if (userData == null) {
            return;
        }
        boolean needSync = false;
        // 更新总武力
        long totalAttack = 0;
        // 更新已拥有的活动门客
        List<JieShiPatronsData> patronsDataList = userData.getPatronsDataList();
        for (JieShiPatronsData patron : patronsDataList) {
            long oldAttack = patron.getAttack();
            long patronsAttack = calcPatronsAttack(patron.getPatronsId());
            if (oldAttack != patronsAttack) {
                needSync = true;
                log.info("【灯火街市】用户id:{},武力值更新,门客id:{},门客武力值:{}", player.getUserId(), patron.getPatronsId(), patronsAttack);
            }
            patron.setAttack(patronsAttack);
            totalAttack += patronsAttack;
        }
        userData.setPatronsDataList(patronsDataList);
        userData.setAttack(totalAttack);
        if (needSync) {
            // 同步下用户数据
            syncUserData();
        }
    }

    /**
     * 计算门客武力值
     *
     * @param patronsId 门客id
     */
    public long calcPatronsAttack(int patronsId) {
        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null) {
            return 0;
        }
        // 获取门客的赚钱
        UserPatrons userPatrons = player.getModule(PatronsModule.class).getUserPatrons(patronsId);
        if (userPatrons == null) {
            return 0;
        }
        String maxParam = config.getLIGHTMARKET_PARTON_TURN_LIMIT_MAX();
        String minParam = config.getLIGHTMARKET_PARTON_TURN_LIMIT_MIN();
        String param = config.getLIGHTMARKET_PARTON_TURN_PARAM();
        // 门客赚钱赚武力公式参数（二次函数a、b、c）千分比
        LightMarketPatronConfig patronConfig = config.getPatronConfigMap().get(userData.getJieDaoSiLevel());
        if (patronConfig == null) {
            return 0;
        }
        // 计算下门客转换武力
        BigDecimal patronsAttack;
        if (userPatrons.getAbility().compareTo(BigInteger.valueOf(Long.parseLong(minParam.split("\\|")[0]))) < 0) {
            patronsAttack = BigDecimal.valueOf(Long.parseLong(minParam.split("\\|")[1]));
        } else if (userPatrons.getAbility().compareTo(BigInteger.valueOf(Long.parseLong(maxParam.split("\\|")[0]))) > 0) {
            patronsAttack = BigDecimal.valueOf(Long.parseLong(maxParam.split("\\|")[1]));
        } else {
            List<Integer> paramList = StringUtils.stringToIntegerList(param, "\\|");
            BigDecimal x = BigDecimal.valueOf(userPatrons.getAbility().longValue()).divide(BigDecimal.valueOf(100000000), 3, RoundingMode.UP);
            patronsAttack = BigDecimal.valueOf(paramList.get(0)).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP).multiply(x).multiply(x)
                    .add(BigDecimal.valueOf(paramList.get(1)).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP).multiply(x))
                    .add(BigDecimal.valueOf(paramList.get(2)).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP))
                    .setScale(0,RoundingMode.UP);
        }
        // 人偶加成
        long dollAddition = getDollAddition(config.getLIGHTMARKET_DOY_WULI_ITEM_ID());
        // 门客最终武力
        patronsAttack = BigDecimal.valueOf(1000 + dollAddition).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP)
                .multiply(patronsAttack.multiply(BigDecimal.valueOf(1000 + patronConfig.getEffect1()).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP)).add(BigDecimal.valueOf(patronConfig.getEffect2())));
        long result = patronsAttack.setScale(0, RoundingMode.UP).longValue();
        return result;
    }

    /**
     * 同步数据
     */
    public void syncData() {
        // 同步用户数据
        syncUserData();
        // 同步配置
        syncConfig();
    }

    /**
     * 同步用户数据
     */
    public void syncUserData() {
        if (userData == null) {
            return;
        }
        // 恢复体力
        recoveryEnergy();
        // 检测下人偶信息
        checkDollExpire();
        // 更新下门客战力
        updatePatronsAttack();
        JieShiProto.JieShiUserDataSyncMsg.Builder builder = JieShiProto.JieShiUserDataSyncMsg.newBuilder();
        builder.setUserData(JieShiPb.parseUserDataTemp(userData));
        player.sendPacket(Protocol.U_JIESHI_USER_DATA_SYNC, builder);
    }

    /**
     * 同步配置
     */
    public void syncConfig() {
        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null) {
            return;
        }
        JieShiProto.JieShiConfigSyncMsg.Builder builder = JieShiProto.JieShiConfigSyncMsg.newBuilder();
        // 街市等级
        for (LightMarketMainLvConfig mainLvConfig : config.getMainLvConfigMap().values()) {
            JieShiProto.LightMarketMainLvConfig.Builder mainLvConfigTemp = JieShiPb.parseLightMarketMainLvConfig(mainLvConfig);
            if (mainLvConfigTemp != null) {
                builder.addMainLvConfig(mainLvConfigTemp);
            }
        }
        // 商铺
        for (LightMarketShopConfig shopConfig : config.getShopConfigMap().values()) {
            JieShiProto.LightMarketShopConfig.Builder shopConfigTemp = JieShiPb.parseLightMarketShopConfig(shopConfig);
            if (shopConfigTemp != null) {
                builder.addShopConfig(shopConfigTemp);
            }
        }
        // 街道司
        for (LightMarketPatronConfig patronConfig : config.getPatronConfigMap().values()) {
            JieShiProto.LightMarketPatronConfig.Builder patronConfigTemp = JieShiPb.parseLightMarketPatronConfig(patronConfig);
            if (patronConfigTemp != null) {
                builder.addPatronConfig(patronConfigTemp);
            }
        }
        // 节奏表
        for (LightMarketRhythmConfig rhythmConfig : config.getRhythmConfigMap().values()) {
            JieShiProto.LightMarketRhythmConfig.Builder rhythmConfigTemp = JieShiPb.parseLightMarketRhythmConfig(rhythmConfig);
            if (rhythmConfigTemp != null) {
                builder.addRhythmConfig(rhythmConfigTemp);
            }
        }
        // 事件表
        for (LightMarketEventConfig eventConfig : config.getEventConfigMap().values()) {
            JieShiProto.LightMarketEventConfig.Builder eventConfigTemp = JieShiPb.parseLightMarketEventConfig(eventConfig, player.getLanguage());
            if (eventConfigTemp != null) {
                builder.addEventConfig(eventConfigTemp);
            }
        }
        player.sendPacket(Protocol.U_JIESHI_CONFIG_SYNC, builder);
    }

    /**
     * 统一校验
     */
    public int preCheck() {
        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null) {
            return GameErrorCode.E_JIESHI_CONFIG_NOT_FOUND;
        }
        ActivityInfo activityInfo = config.getActivityInfo();
        if (activityInfo == null) {
            return GameErrorCode.E_JIESHI_ACTIVITY_NOT_FOUND;
        }
        if (!ActivityMgr.activityInTime(activityInfo)) {
            return GameErrorCode.E_JIESHI_ACTIVITY_NOT_IN_TIME;
        }
        if (userData == null) {
            return GameErrorCode.E_JIESHI_SYSTEM_NOT_OPEN;
        }
        return 0;
    }

    /**
     * 完成新手引导
     */
    public int finishGuide() {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        userData.setGuide(true);
        JieShiProto.JieShiFinishGuideRespMsg.Builder respMsg = JieShiProto.JieShiFinishGuideRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setGuide(userData.isGuide());
        player.sendPacket(Protocol.U_JIESHI_FINISH_GUIDE, respMsg);
        return 0;
    }

    /**
     * 随机名字
     */
    public int randomName() {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        JieShiConfig config = JieShiMgr.getConfig();
        String key = "LIGHTMARKET_MAIN_NAME_" + randomHelper.next(1, config.getLIGHTMARKET_NAME_NUM() + 1);
        JieShiProto.JieShiRandomNameRespMsg.Builder respMsg = JieShiProto.JieShiRandomNameRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setRandomName(MultipleLanguageMgr.getContent(key, player.getLanguage()));
        player.sendPacket(Protocol.U_JIESHI_RANDOM_NAME, respMsg);
        return 0;
    }

    /**
     * 更改名字
     * @param nickName  修改昵称
     */
    public int changeNickName(String nickName) {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        //清前后空格
        nickName = StringUtils.clearHeadAndTailEmpty(nickName);
        int nameLength = StringUtils.getStringLen(nickName);
        //名字长度限制
        if (nameLength > JieShiMgr.JIESHI_MAX_NICK_NAME_LENGTH || nameLength < JieShiMgr.JIESHI_MIN_NICK_NAME_LENGTH) {
            return GameErrorCode.E_NAME_LENGTH_OVER;
        }
        //敏感词限制
        if (ForbiddenWordMgr.isNickNameForbidden(nickName)) {
            return GameErrorCode.E_FORBIDDEN_WORD;
        }
        // 只有引导未完成才能修改
        if (userData.getChangeNameTimes() >= 1) {
            return GameErrorCode.E_JIESHI_DONT_CHANGE_NAME;
        }
        userData.setNickName(nickName);
        userData.setChangeNameTimes(userData.getChangeNameTimes() + 1);
        // 更新下排行榜
        player.notifyListener(eGamePlayerEventType.JieShiJiaoZiRank.getValue(), new JieShiJiaoZiRankParam(BigInteger.valueOf(userData.getScore()), userData.getNickName()));

        JieShiProto.JieShiChangeNameRespMsg.Builder respMsg = JieShiProto.JieShiChangeNameRespMsg.newBuilder();
        respMsg.setRet(0);
        player.sendPacket(Protocol.U_JIESHI_CHANGE_NAME, respMsg);
        return 0;
    }
    /**
     * 重置街市地块
     */
    public int resetPosition() {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null) {
            return GameErrorCode.E_JIESHI_CONFIG_NOT_FOUND;
        }
        if (userData.getUnlockPosition().size() == 0) {
            return GameErrorCode.E_JIESHI_NO_POSITION_TO_RESET;
        }
        // 消耗道具
        Property property = PropertyHelper.parseStringToProperty(config.getLIGHTMARKET_RESET_COST());
        if (!player.getModule(CurrencyModule.class).removeCurrency(property, eLogMoneyType.JieShi, eLogMoneyType.JieShiResetPosition)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        // 计算下能返还多少消耗
        int size = userData.getUnlockPosition().size();
        List<Integer> costList = StringUtils.stringToIntegerList(config.getLIGHTMARKET_MAP_UNLOCK_COST(), "\\|");
        long totalJiaoZi = 0;
        for (int i = 0; i < size; i++) {
            totalJiaoZi += costList.get(Math.min(i, costList.size() - 1));
        }
        userData.setUnlockPosition(new ArrayList<>());
        userData.setMapBuildList(new ArrayList<>());
        userData.setJiaoZi(userData.getJiaoZi() + totalJiaoZi);
        JieShiProto.JieShiResetPositionRespMsg.Builder respMsg = JieShiProto.JieShiResetPositionRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUserData(JieShiPb.parseUserDataTemp(userData));
        player.sendPacket(Protocol.U_JIESHI_RESET_POSITION, respMsg);
        return 0;
    }


    /**
     * 招募门客
     * 待选的门客
     */
    public int choosePatrons(List<Integer> patronsIdList) {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        // 判断门客是否存在
        for (Integer patronsId : patronsIdList) {
            UserPatrons userPatrons = player.getModule(PatronsModule.class).getUserPatrons(patronsId);
            if (userPatrons == null) {
                return GameErrorCode.E_PATRONS_NO_FOUND;
            }
        }
        JieShiConfig config = JieShiMgr.getConfig();
        // 判断是否达到上限了
        LightMarketPatronConfig patronConfig = config.getPatronConfigMap().get(userData.getJieDaoSiLevel());
        if (patronConfig == null) {
            return GameErrorCode.E_JIESHI_CONFIG_NOT_FOUND;
        }
        // 可携带的门客数量
        int partonNum = patronConfig.getPartonNum();
        // 当前的门客数量
        if (patronsIdList.size() > partonNum) {
            return GameErrorCode.E_JIESHI_PATRONS_NUM_LIMIT;
        }
        // 招募门客
        List<JieShiPatronsData> patronsDataList = new ArrayList<>();
        for (Integer patronsId : patronsIdList) {
            JieShiPatronsData patronsData = new JieShiPatronsData();
            patronsData.setPatronsId(patronsId);
            patronsDataList.add(patronsData);
        }
        List<Integer> beforePatronsIdList = new ArrayList<>();
        for (JieShiPatronsData patronsData : userData.getPatronsDataList()) {
            beforePatronsIdList.add(patronsData.getPatronsId());
        }
        long oldAttack = userData.getAttack();
        userData.setPatronsDataList(patronsDataList);
        // 更新下门客的武力值
        updatePatronsAttack();
        // 下发数据
        JieShiProto.JieDaoSiChoosePatronsRespMsg.Builder builder = JieShiProto.JieDaoSiChoosePatronsRespMsg.newBuilder();
        builder.setRet(0);
        builder.setAttack(userData.getAttack());
        // 已拥有的活动门客数据
        for (JieShiPatronsData patron : userData.getPatronsDataList()) {
            JieShiProto.JieShiPatronsDataTemp.Builder patronsDataTemp = JieShiPb.parsePatronsDataTemp(patron);
            if (patronsDataTemp != null) {
                builder.addPatrons(patronsDataTemp);
            }
        }
        player.sendPacket(Protocol.U_JIESHI_CHOOSE_PATRON, builder);
        // 门客日志
        AutoLogMgr.add(new LogJieShiPatrons(
                config.getActivityInfo().getActivityId(),
                player.getUserId(),
                JSON.toJSONString(beforePatronsIdList),
                JSON.toJSONString(patronsIdList),
                oldAttack,
                userData.getAttack()
        ));
        return 0;
    }

    /**
     * 街道司升级
     */
    public int upgradeJieDaoSiLevel() {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        JieShiConfig config = JieShiMgr.getConfig();
        // 判断下等级是否达到上限
        // 当前等级
        int jieDaoSiLevel = userData.getJieDaoSiLevel();
        LightMarketPatronConfig nextPatronConfig = config.getPatronConfigMap().get(jieDaoSiLevel + 1);
        if (nextPatronConfig == null) {
            return GameErrorCode.E_JIESHI_JIEDAOSI_MAX_LEVEL;
        }
        // 判断消耗
        LightMarketPatronConfig patronConfig = config.getPatronConfigMap().get(jieDaoSiLevel);
        long cost = Long.parseLong(patronConfig.getCost());
        if (userData.getJiaoZi() < cost) {
            return GameErrorCode.E_JIESHI_ITEM_NOT_ENOUGH;
        }
        int oldLevel = userData.getJieDaoSiLevel();
        long oldAttack = userData.getAttack();
        long oldJiaoZi = userData.getJiaoZi();
        // 扣消耗
        userData.setJiaoZi(userData.getJiaoZi() - cost);
        // 升级
        userData.setJieDaoSiLevel(userData.getJieDaoSiLevel() + 1);
        // 更新下武力值
        updatePatronsAttack();
        JieShiProto.JieDaoSiUpgradeRespMsg.Builder builder = JieShiProto.JieDaoSiUpgradeRespMsg.newBuilder();
        builder.setRet(0);
        builder.setUserData(JieShiPb.parseUserDataTemp(userData));
        player.sendPacket(Protocol.U_JIESHI_UPGRADE_JIEDAOSI_LEVEL, builder);
        // 升级日志
        AutoLogMgr.add(new LogJieShiUpgrade(
                config.getActivityInfo().getActivityId(),
                player.getUserId(),
                2,
                oldLevel,
                userData.getJieShiLevel(),
                oldAttack,
                userData.getAttack(),
                oldJiaoZi,
                cost,
                userData.getJiaoZi()
        ));
        return 0;
    }

    /**
     * 客户端拉取用户数据
     */
    public int getUserDataByCmd() {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        // 恢复体力
        recoveryEnergy();
        // 检测下人偶信息
        checkDollExpire();
        // 更新下门客战力
        updatePatronsAttack();
        JieShiProto.JieShiGetUserDataRespMsg.Builder respMsg = JieShiProto.JieShiGetUserDataRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setUserData(JieShiPb.parseUserDataTemp(userData));
        player.sendPacket(Protocol.U_JIESHI_GET_USER_DATA, respMsg);
        return 0;
    }

    /**
     * 街市升级
     */
    public int upgradeJieShiLevel() {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        JieShiConfig config = JieShiMgr.getConfig();
        // 判断街市是否达到上限
        LightMarketMainLvConfig nextMainLvConfig = config.getMainLvConfigMap().get(userData.getJieShiLevel() + 1);
        if (nextMainLvConfig == null) {
            return GameErrorCode.E_JIESHI_JIESHI_MAX_LEVEL;
        }
        LightMarketMainLvConfig mainLvConfig = config.getMainLvConfigMap().get(userData.getJieShiLevel());
        // 判断消耗
        long cost = Long.parseLong(mainLvConfig.getUpCost());
        if (userData.getJiaoZi() < cost) {
            return GameErrorCode.E_JIESHI_ITEM_NOT_ENOUGH;
        }
        int oldLevel = userData.getJieShiLevel();
        long oldAttack = userData.getAttack();
        long oldJiaoZi = userData.getJiaoZi();
        // 扣消耗
        userData.setJiaoZi(userData.getJiaoZi() - cost);
        // 升级
        userData.setJieShiLevel(userData.getJieShiLevel() + 1);
        // 街市等级成就
        player.notifyListener(eGamePlayerEventType.JieShiLevel.getValue(), BigInteger.valueOf(userData.getJieShiLevel()));
        JieShiProto.JieShiUpgradeRespMsg.Builder builder = JieShiProto.JieShiUpgradeRespMsg.newBuilder();
        builder.setRet(0);
        builder.setJieShiLevel(userData.getJieShiLevel());
        builder.setJiaoZi(userData.getJiaoZi());
        player.sendPacket(Protocol.U_JIESHI_UPGRADE_JIESHI_LEVEL, builder);
        // 升级日志
        AutoLogMgr.add(new LogJieShiUpgrade(
                config.getActivityInfo().getActivityId(),
                player.getUserId(),
                1,
                oldLevel,
                userData.getJieShiLevel(),
                oldAttack,
                userData.getAttack(),
                oldJiaoZi,
                cost,
                userData.getJiaoZi()
        ));
        return 0;
    }

    /**
     * 解锁地块
     */
    public int unlockPosition(int position) {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        JieShiConfig config = JieShiMgr.getConfig();
        // 判断是否已解锁
        List<Integer> unlockPosition = userData.getUnlockPosition();
        if (unlockPosition.contains(position)) {
            return GameErrorCode.E_JIESHI_POSITION_ALREADY_UNLOCK;
        }
        // 判断是否能解锁，只有特殊地块才需解锁
        Map<Integer, Integer> jieShiMap = config.getJieShiMap();
        if (!jieShiMap.containsKey(position)) {
            return GameErrorCode.E_JIESHI_POSITION_NOT_FOUND;
        }
        if (jieShiMap.get(position) != eJieShiPositionType.Special.getValue()) {
            return GameErrorCode.E_JIESHI_POSITION_NO_NEED_UNLOCK;
        }
        // 判断消耗
        // 获取消耗
        List<Long> costList = StringUtils.stringToLongList(config.getLIGHTMARKET_MAP_UNLOCK_COST(), "\\|");
        // 当前解锁的地块
        int unlockSize = unlockPosition.size();
        long needCost = costList.get(Math.min(unlockSize, costList.size() - 1));
        if (userData.getJiaoZi() < needCost) {
            return GameErrorCode.E_JIESHI_ITEM_NOT_ENOUGH;
        }
        long oldJiaoZi = userData.getJiaoZi();
        // 扣除消耗
        userData.setJiaoZi(userData.getJiaoZi() - needCost);
        // 解锁地块
        unlockPosition.add(position);
        userData.setUnlockPosition(unlockPosition);
        JieShiProto.JieShiUnlockPositionRespMsg.Builder builder = JieShiProto.JieShiUnlockPositionRespMsg.newBuilder();
        builder.setRet(0);
        builder.addAllUnlockPosition(userData.getUnlockPosition());
        builder.setJiaoZi(userData.getJiaoZi());
        player.sendPacket(Protocol.U_JIESHI_UNLOCK_POSITION, builder);
        // 解锁日志
        AutoLogMgr.add(new LogJieShiUnlockPosition(
                config.getActivityInfo().getActivityId(),
                player.getUserId(),
                position,
                oldJiaoZi,
                needCost,
                userData.getJiaoZi()
        ));
        return 0;
    }

    /**
     * 自然恢复体力逻辑
     */
    public void recoveryEnergy(){
        JieShiConfig config = JieShiMgr.getConfig();
        if(userData != null && config != null){
            // 计算
            CalcPowerResult result = PowerHelper.calcPower(
                    userData.getLastEnergyRecTime() / 1000,
                    config.getLIGHTMARKET_ENERGY_RECOVERY_TIME(),
                    config.getLIGHTMARKET_ENERGY_RECOVERY_NUM(),
                    config.getLIGHTMARKET_ENERGY_MAX_NUM(),
                    userData.getEnergy()
            );
            int oldEnergy = userData.getEnergy();
            // 更新内存
            userData.setEnergy(result.getCurPower());
            userData.setLastEnergyRecTime(result.getLastRecoverTime() * 1000);
            // 体力日志
            AutoLogMgr.add(new LogJieShiEnergy(
                    config.getActivityInfo().getActivityId(),
                    player.getUserId(),
                    1,
                    oldEnergy,
                    userData.getEnergy() - oldEnergy,
                    userData.getEnergy()
            ));
        }
    }


    /**
     * 使用体力道具
     */
    public int useEnergyItem(int count) {
        if (count <= 0 || count > 9999) {
            return GameErrorCode.E_JIESHI_PARAM_ERROR;
        }
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        JieShiConfig config = JieShiMgr.getConfig();
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(config.getLIGHTMARKET_ENERGY_ITEM_ID());
        if (goodsInfo == null) {
            return GameErrorCode.E_JIESHI_CONFIG_NOT_FOUND;
        }
        Property cost = new Property(config.getLIGHTMARKET_ENERGY_ITEM_ID(), count);

        // 扣道具
        if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.JieShi, eLogMoneyType.JieShiEnergyItemConsume)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        // 计算恢复数量
        int totalCount = goodsInfo.getParamList().get(0).intValue() * count;

        // 恢复体力
        recoveryEnergy();
        int oldEnergy = userData.getEnergy();
        // 加体力
        userData.setEnergy(userData.getEnergy() + totalCount);
        if (userData.getEnergy() >= config.getLIGHTMARKET_ENERGY_MAX_NUM()) {
            userData.setLastEnergyRecTime(System.currentTimeMillis());
        }
        // 客户端
        JieShiProto.JieShiRecoveryEnergyRespMsg.Builder builder = JieShiProto.JieShiRecoveryEnergyRespMsg.newBuilder();
        builder.setRet(0);
        builder.setEnergy(userData.getEnergy());
        builder.setLastEnergyRecTime(userData.getLastEnergyRecTime());
        player.sendPacket(Protocol.U_JIESHI_USE_ENERGY_ITEM, builder);

        // 体力日志
        AutoLogMgr.add(new LogJieShiEnergy(
                config.getActivityInfo().getActivityId(),
                player.getUserId(),
                2,
                oldEnergy,
                userData.getEnergy() - oldEnergy,
                userData.getEnergy()
        ));
        return 0;
    }

    /**
     * 更换人偶
     */
    public int changeDoll(int dollId) {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        // 判断下人偶是否存在
        boolean isFind = userData.getDollList().stream().anyMatch(dollData -> dollData.getDollId() == dollId);
        if (!isFind) {
            return GameErrorCode.E_JIESHI_DOLL_NOT_FOUND;
        }
        List<JieShiDollData> dollList = userData.getDollList();
        for (JieShiDollData dollData : dollList) {
            if (dollData.getDollId() == dollId) {
                //人偶过期
                if (dollData.getExpireTime() != 0 && System.currentTimeMillis() >= dollData.getExpireTime()) {
                    return GameErrorCode.E_JIESHI_DOLL_OVER_TIME;
                } else {
                    userData.setDollId(dollId);
                    break;
                }
            }
        }
        JieShiProto.JieShiChangeDollRespMsg.Builder builder = JieShiProto.JieShiChangeDollRespMsg.newBuilder();
        builder.setRet(0);
        builder.setDollId(userData.getDollId());
        player.sendPacket(Protocol.U_JIESHI_CHANGE_DOLL, builder);
        return 0;
    }

    /**
     * 解锁人偶
     */
    public int unlockDoll(int dollId, int count) {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null) {
            return GameErrorCode.E_JIESHI_CONFIG_NOT_FOUND;
        }
        GoodsInfo goodsInfo = CommonMgr.getGoodsInfo(dollId);
        if (goodsInfo == null) {
            return GameErrorCode.E_JIESHI_DOLL_ITEM_NOT_FOUND;
        }
        // 消耗道具
        // 扣道具
        Property cost = new Property(dollId, count);
        if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.JieShi, eLogMoneyType.JieShiUnlockDoll)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        // 添加人偶
        addDoll(dollId, count);
        // 自动使用人偶
        userData.setDollId(dollId);
        if (dollId == config.getLIGHTMARKET_DOY_WULI_ITEM_ID()) {
            updatePatronsAttack();
        }
        JieShiProto.JieShiUnlockDollRespMsg.Builder builder = JieShiProto.JieShiUnlockDollRespMsg.newBuilder();
        builder.setRet(0);
        builder.setDollId(userData.getDollId());
        // 拥有的人偶列表
        for (JieShiDollData dollData : userData.getDollList()) {
            JieShiProto.JieShiDollDataTemp.Builder dollDataTemp = JieShiPb.parseDollDataTemp(dollData);
            if (dollDataTemp != null) {
                builder.addDollList(dollDataTemp);
            }
        }
        player.sendPacket(Protocol.U_JIESHI_UNLOCK_DOLL, builder);
        return 0;
    }


    /**
     * 添加人偶
     */
    public void addDoll(int dollId, int count) {
        long now = System.currentTimeMillis();
        long addTime = 0;
        GoodsInfo goodsInfo = CommonMgr.getGoodsInfo(dollId);
        //  有效期
        if (goodsInfo != null) {
            int time = goodsInfo.getParamList().get(1).intValue();
            if (time > 0) {
                addTime = 1000L * time * count;
            }
        }
        boolean isFind = false;
        List<JieShiDollData> dollList = userData.getDollList();
        for (JieShiDollData dollData : dollList) {
            // 有人偶
            if (dollData.getDollId() == dollId) {
                long expireTime = dollData.getExpireTime();
                if (expireTime < now) {
                    dollData.setExpireTime(now + addTime);
                } else {
                    dollData.setExpireTime(expireTime + addTime);
                }
                isFind = true;
                break;
            }
        }
        if (!isFind) {
            // 没人偶
            JieShiDollData dollData = new JieShiDollData(dollId, now + addTime);
            dollList.add(dollData);
        }
        userData.setUpdateOption();
    }

    /**
     * 人偶过期检测（帮他换形象）
     */
    public void checkDollExpire() {
        if (userData == null) {
            return;
        }
        int dollId = userData.getDollId();
        List<JieShiDollData> dollList = userData.getDollList();
        long now = System.currentTimeMillis();
        for (JieShiDollData dollData : dollList) {
            if (dollData.getDollId() == dollId) {
                // 当前使用的人偶过期了，换回默认形象
                long expireTime = dollData.getExpireTime();
                if (expireTime != 0 && expireTime <= now) {
                    userData.setDollId(JieShiMgr.getConfig().getLIGHTMARKET_DOY_DEFAULT_ITEM_ID());
                }
                break;
            }
        }
    }

    /**
     * 空地上是否能建造
     * 默认解锁或者已解锁
     */
    public boolean canBuildInPosition(int position) {
        if (userData == null) {
            return false;
        }
        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null) {
            return false;
        }
        Map<Integer, Integer> jieShiMap = config.getJieShiMap();
        if (!jieShiMap.containsKey(position)) {
            return false;
        }
        return userData.getUnlockPosition().contains(position) || jieShiMap.get(position) == eJieShiPositionType.DefaultUnLock.getValue();
    }

    /**
     * 判断食物是否足够
     * @param buildDataList 建筑列表
     */
    public boolean checkFoodEnough(List<JieShiMapBuildData> buildDataList) {
        if (userData == null) {
            return false;
        }
        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null) {
            return false;
        }
        int totalFood = 0;
        for (JieShiMapBuildData buildData : buildDataList) {
            LightMarketShopConfig shopConfig = config.getShopConfigMap().get(buildData.getBuildId());
            if (shopConfig == null) {
                continue;
            }
            long food = 0;
            if (shopConfig.getType() == eJieShiShopType.Snacks.getValue()) {
                // 计算下食物加成
                long addition = getBuildAddition(buildDataList, buildData, 2);
                food = BigDecimal.valueOf(shopConfig.getFood()).multiply(BigDecimal.valueOf(1000).add(BigDecimal.valueOf(addition))).divide(BigDecimal.valueOf(1000), 0, RoundingMode.UP).longValue();
            } else {
                food = shopConfig.getFood();
            }
            totalFood += food;
        }
        // 判断下食物占用
        return totalFood >= 0;
    }

    /**
     * 营造
     */
    public int finishBuild(List<JieShiMapBuildData> buildDataList) {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        JieShiConfig config = JieShiMgr.getConfig();
        // 判断下是否建造上限
        LightMarketMainLvConfig mainLvConfig = config.getMainLvConfigMap().get(userData.getJieShiLevel());
        int buildLimit = mainLvConfig.getBuildMaxNum();
        if (buildDataList.size() > buildLimit) {
            return GameErrorCode.E_JIESHI_BUILD_NUM_LIMIT;
        }
        Map<Integer, Integer> jieShiMap = config.getJieShiMap();
        // 判断下地块是否可建造
        Set<Integer> occupyPosition = new HashSet<>();
        for (JieShiMapBuildData buildData : buildDataList) {
            for (int position : buildData.getPosition()) {
                if (!occupyPosition.add(position)) {
                    return GameErrorCode.E_JIESHI_BUILD_POSITION_OVERLAP;
                }
                if (!jieShiMap.containsKey(position)) {
                    return GameErrorCode.E_JIESHI_POSITION_NOT_FOUND;
                }
                if (!canBuildInPosition(position)) {
                    return GameErrorCode.E_JIESHI_POSITION_DONT_BUILD;
                }
            }
        }
        // 判断下食物占用
        if (!checkFoodEnough(buildDataList)) {
            return GameErrorCode.E_JIESHI_FOOD_NO_ENOUGH;
        }
        // 类型1|类型2|类型3  => 类型 商铺id1;商铺id2;商铺id3
        Map<Integer, Integer> buildCnt = new HashMap<>();
        for (JieShiMapBuildData buildData : buildDataList) {
            buildCnt.put(buildData.getBuildId(), buildCnt.getOrDefault(buildData.getBuildId(), 0) + 1);
        }
        String[] typeMaxNumList = mainLvConfig.getBuildTypeMaxNum().split("\\|");
        for (int i = 0; i < typeMaxNumList.length; i++) {
            int type = i + 1;
            String[] buildMaxNumParam = typeMaxNumList[i].split(";");
            for (int j = 0; j < buildMaxNumParam.length; j++) {
                // 获取下id
                int buildId = config.getBuildIdByTypeAndIdx(type, j);
                if (buildId != 0) {
                    // 超出建筑上限
                    if (buildCnt.getOrDefault(buildId, 0) > Integer.parseInt(buildMaxNumParam[j])) {
                        return GameErrorCode.E_JIESHI_BUILD_TYPE_NUM_LIMIT;
                    }
                }
            }
        }
        // 保存
        userData.setMapBuildList(buildDataList);
        JieShiProto.JieShiFinishBuildRespMsg.Builder builder = JieShiProto.JieShiFinishBuildRespMsg.newBuilder();
        builder.setRet(0);
        for (JieShiMapBuildData mapBuildData : userData.getMapBuildList()) {
            JieShiProto.JieShiMapBuildDataTemp.Builder mapBuildDataTemp = JieShiPb.parseMapBuildDataTemp(mapBuildData);
            if (mapBuildDataTemp != null) {
                builder.addMapBuildList(mapBuildDataTemp);
            }
        }
        player.sendPacket(Protocol.U_JIESHI_FINISH_BUILD, builder);
        // 营造日志
        AutoLogMgr.add(new LogJieShiBuild(
                config.getActivityInfo().getActivityId(),
                player.getUserId(),
                userData.getJieShiLevel(),
                JSON.toJSONString(userData.getMapBuildList())
        ));
        return 0;
    }

    /**
     * 处理事件
     *
     * @param eventId 事件id
     * @param param   事件参数 二选一事件传1或者2
     */
    public int handlerEvent(int position, int eventId, String param) {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        JieShiConfig config = JieShiMgr.getConfig();
        LightMarketEventConfig eventConfig = config.getEventConfigMap().get(eventId);
        if (eventConfig == null) {
            return GameErrorCode.E_JIESHI_CONFIG_NOT_FOUND;
        }
        JieShiEventData eventData = null;
        List<JieShiEventData> eventList = userData.getEventList();
        for (JieShiEventData eventData1 : eventList) {
            if (eventData1.getEventId() == eventId && eventData1.getPosition() == position) {
                eventData = eventData1;
                break;
            }
        }
        if (eventData == null) {
            return GameErrorCode.E_JIESHI_EVENT_NOT_FOUND;
        }
        // 移除事件
        eventList.remove(eventData);
        userData.setEventList(eventList);
        // 获得交子奖励
        long addJiaoZi = 0;
        String rewardStr = "";
        // 处理事件
        if (eventConfig.getType() == 1) {
            // 二选一事件
            LightMarketRhythmConfig rhythmConfig = config.getRhythmConfigMap().get(Math.min(eventData.getGenRound(), config.getRhythmConfigMap().size()));
            String[] split = eventConfig.getRewards().split("#");
            // 交子奖励
            List<Integer> jiaoZiList = StringUtils.stringToIntegerList(split[0], "\\|");
            // 道具奖励
            List<String> rewardList = StringUtils.stringToStringList(split[1], "\\|");
            if ("1".equals(param)) {
                addJiaoZi = BigDecimal.valueOf(Long.parseLong(rhythmConfig.getStandardMoneySpeed())).multiply(BigDecimal.valueOf(jiaoZiList.get(0))).divide(BigDecimal.valueOf(1000), 0, RoundingMode.UP).longValue();
                rewardStr = rewardList.get(0);
            } else if ("2".equals(param)) {
                addJiaoZi = BigDecimal.valueOf(Long.parseLong(rhythmConfig.getStandardMoneySpeed())).multiply(BigDecimal.valueOf(jiaoZiList.get(1))).divide(BigDecimal.valueOf(1000), 0, RoundingMode.UP).longValue();
                rewardStr = rewardList.get(1);
            }
            player.getModule(CurrencyModule.class).addCurrency(PropertyHelper.parseStringToProperty(rewardStr), eLogMoneyType.JieShi, eLogMoneyType.JieShiEvent1Reward);
            if (Config.isDebug()) {
                log.info("【灯火街市】用户id:{},完成二选一事件,选择:{},获得交子:{},获得道具奖励:{}", player.getUserId(), param, addJiaoZi, rewardStr);
            }

            AutoLogMgr.add(new LogJieShiChoseEvent(config.getActivityInfo().getActivityId(), player.getUserId(), userData.getJieShiLevel(), eventConfig.getType(), eventConfig.getId(), eventData.getGenRound(), userData.getTravelTimes()));
        }
        // 获得交子
        addJiaoZi(addJiaoZi);
        JieShiProto.JieShiHandlerEventRespMsg.Builder builder = JieShiProto.JieShiHandlerEventRespMsg.newBuilder();
        builder.setRet(0);
        builder.setAddJiaoZi(addJiaoZi);
        builder.setReward(rewardStr);
        builder.setJiaoZi(userData.getJiaoZi());
        // 地图上的事件列表
        for (JieShiEventData data : userData.getEventList()) {
            JieShiProto.JieShiEventDataTemp.Builder eventDataTemp = JieShiPb.parseEventDataTemp(data);
            if (eventDataTemp != null) {
                builder.addEventList(eventDataTemp);
            }
        }
        player.sendPacket(Protocol.U_JIESHI_HANDLER_EVENT, builder);
        return 0;
    }

    /**
     * 添加交子
     */
    public void addJiaoZi(long addJiaoZi) {
        if (userData == null || addJiaoZi == 0) {
            return;
        }
        if (Config.isDebug()) {
            log.info("【灯火街市】用户id:{},交子变动:{}", player.getUserId(), addJiaoZi);
        }
        userData.setJiaoZi(userData.getJiaoZi() + addJiaoZi);
        userData.setScore(userData.getScore() + addJiaoZi);
        player.notifyListener(eGamePlayerEventType.JieShiTotalJiaoZi.getValue(), BigInteger.valueOf(userData.getScore()));
        player.notifyListener(eGamePlayerEventType.JieShiJiaoZiRank.getValue(), new JieShiJiaoZiRankParam(BigInteger.valueOf(userData.getScore()), userData.getNickName()));
    }


    /**
     * 巡游
     */
    public int travel() {
        int preCheck = preCheck();
        if (preCheck != 0) {
            return preCheck;
        }
        long start = System.currentTimeMillis();
        log.info("【街市巡游】用户id:{},步骤1,耗时:{} ms ", player.getUserId(), System.currentTimeMillis() - start);
        // 恢复一下体力
        recoveryEnergy();
        JieShiConfig config = JieShiMgr.getConfig();
        LightMarketPatronConfig patronConfig = config.getPatronConfigMap().get(userData.getJieDaoSiLevel());
        // 这一圈的圈数
        int curRound = userData.getTravelTimes() + 1;
        // 获取体力消耗
        int roundCost = 1;
        // 建筑产出倍数千分比
        int buildRoundAdd = 1000;
        List<String> roundCostList = StringUtils.stringToStringList(config.getLIGHTMARKET_ROUND_COST(), "\\|");
        for (String roundCostParam : roundCostList) {
            String[] split = roundCostParam.split(";");
            if (curRound >= Integer.parseInt(split[0])) {
                roundCost = Integer.parseInt(split[1]);
                buildRoundAdd = Integer.parseInt(split[2]);
            }
        }
        if (userData.getEnergy() < roundCost) {
            return GameErrorCode.E_JIESHI_ENERGY_NO_ENOUGH;
        }
        log.info("【街市巡游】用户id:{},步骤2,耗时:{} ms ", player.getUserId(), System.currentTimeMillis() - start);
        // 统计下商铺的数量，没有商铺不让巡游
        int storeCount = 0;
        for (JieShiMapBuildData buildData : userData.getMapBuildList()) {
            LightMarketShopConfig shopConfig = config.getShopConfigMap().get(buildData.getBuildId());
            if (shopConfig.getType() == eJieShiShopType.Store.getValue()) {
                storeCount++;
            }
        }
        if (storeCount == 0) {
            return GameErrorCode.E_JIESHI_TRAVEL_NO_BUILD;
        }
        if (!checkFoodEnough(userData.getMapBuildList())) {
            return GameErrorCode.E_JIESHI_FOOD_NO_ENOUGH;
        }
        int oldEnergy = userData.getEnergy();
        // 扣除体力
        userData.setEnergy(userData.getEnergy() - roundCost);
        // 开始巡游
        // 获取地图
        log.info("【街市巡游】用户id:{},步骤3,耗时:{} ms ", player.getUserId(), System.currentTimeMillis() - start);
        Map<Integer, Integer> jieShiMap = config.getJieShiMap();
        int mapWidth = config.getMapWidth();
        // 巡游过程
        List<JieShiTravelResultData> resultDataList = new ArrayList<>();
        // 获取地图路线-->按路线巡游
        List<Integer> path = config.getJieShiMapPath();
        // 上下左右
        int[] direction = new int[]{-mapWidth, mapWidth, -1, 1};
        // 总获得的交子
        long totalAddJiaoZi = 0;
        List<JieShiRuffianData> ruffianList = userData.getRuffianList();
        List<JieShiEventData> eventList = userData.getEventList();
        Property reward = new Property();
        // 事件日志记录
        List<Integer> logEventId = new ArrayList<>();
        List<Integer> logEventResult = new ArrayList<>();
        for (int position : path) {
            Property eventReward = new Property();
            // 是否需要处理标识 （有商铺产出，或者有事件产生）
            boolean flag = false;
            // 判断下有没有泼皮
            JieShiRuffianData ruffianData = getJieShiRuffianDataByPosition(position);
            if (ruffianData != null) {
                // 判断是否能打过
                if (userData.getAttack() >= ruffianData.getAttack()) {
                    // 打过了，获得交子奖励
                    totalAddJiaoZi += ruffianData.getJiaoZi();
                    // 移除泼皮
                    ruffianList.remove(ruffianData);
                    userData.setRuffianList(ruffianList);
                    // 获得道具奖励
                    eventReward = PropertyHelper.parseStringToProperty(config.getRascalReward(curRound));
                    reward.addProperty(eventReward);
                    if (Config.isDebug()) {
                        log.info("【灯火街市】用户id:{},击败泼皮,道路位置:{},泼皮id:{},泼皮武力:{},获得交子:{},获得道具奖励", player.getUserId(), ruffianData.getPosition(), ruffianData.getEventId(), ruffianData.getAttack(), ruffianData.getJiaoZi());
                    }
                    // 泼皮日志
                    AutoLogMgr.add(new LogJieShiRuffianBattle(
                            config.getActivityInfo().getActivityId(),
                            player.getUserId(),
                            curRound,
                            ruffianData.getEventId(),
                            ruffianData.getGenRound(),
                            ruffianData.getAttack(),
                            userData.getAttack(),
                            true,
                            ruffianData.getJiaoZi()
                    ));
                    logEventId.add(ruffianData.getEventId());
                    logEventResult.add(1);
                } else {
                    // 没打过
                    if (Config.isDebug()) {
                        log.info("【灯火街市】用户id:{},没打过泼皮,道路位置:{},泼皮id:{},泼皮武力:{},泼皮拥有交子:{}", player.getUserId(), ruffianData.getPosition(), ruffianData.getEventId(), ruffianData.getAttack(), ruffianData.getJiaoZi());
                    }
                    // 泼皮日志
                    AutoLogMgr.add(new LogJieShiRuffianBattle(
                            config.getActivityInfo().getActivityId(),
                            player.getUserId(),
                            curRound,
                            ruffianData.getEventId(),
                            ruffianData.getGenRound(),
                            ruffianData.getAttack(),
                            userData.getAttack(),
                            false,
                            0
                    ));
                    logEventId.add(ruffianData.getEventId());
                    logEventResult.add(0);
                }
                log.info("【街市巡游】用户id:{},步骤4,打泼皮,耗时:{} ms ", player.getUserId(), System.currentTimeMillis() - start);
            }
            // 判断下有没有事件
            JieShiEventData eventData = getJieShiEventDataByPosition(position);
            if (eventData != null) {
                int eventId = eventData.getEventId();
                LightMarketEventConfig eventConfig = config.getEventConfigMap().get(eventId);
                boolean finishEvent = false;
                // 触发事件
                if (eventConfig.getType() == 2) {
                    // 关扑事件
                    // 获得奖励
                    eventReward = PropertyHelper.parseStringToProperty(eventConfig.getRewards());
                    reward.addProperty(eventReward);
                    if (Config.isDebug()) {
                        log.info("【灯火街市】用户id:{},地图位置:{},触发关扑事件,获得奖励:{}", player.getUserId(), position, eventConfig.getRewards());
                    }
                    finishEvent = true;
                }
                // 添加buff事件
                if (isEventBuff(eventId)) {
                    addBuff(eventId);
                    if (Config.isDebug()) {
                        log.info("【灯火街市】用户id:{},地图位置:{},触发buff事件,添加buff:{}", player.getUserId(), position, eventId);
                    }
                    finishEvent = true;
                }
                if (finishEvent) {
                    // 处理完后移除事件
                    eventList.remove(eventData);
                    userData.setEventList(eventList);
                    logEventId.add(eventData.getEventId());
                    logEventResult.add(1);
                }
                log.info("【街市巡游】用户id:{},步骤4,触发事件,耗时:{} ms ", player.getUserId(), System.currentTimeMillis() - start);
            }
            long totalMoney = 0;
            // 判断下上下左右的商铺
            for (int dir : direction) {
                int newPosition = position + dir;
                if (!jieShiMap.containsKey(newPosition)) {
                    continue;
                }
                JieShiMapBuildData buildData = getMapBuildInPosition(newPosition);
                if (buildData == null) {
                    continue;
                }
                LightMarketShopConfig shopConfig = config.getShopConfigMap().get(buildData.getBuildId());
                if (shopConfig == null) {
                    continue;
                }
                if (shopConfig.getType() == eJieShiShopType.Store.getValue()) {
                    // 计算下交子加成（含自身）
                    long buildAddition = 1000 + getBuildAddition(userData.getMapBuildList(), buildData, 1);
                    // 获取泼皮的影响的收益
                    long totalRuffianAddition = 0;
                    for (JieShiRuffianData ruffian : userData.getRuffianList()) {
                        LightMarketShopConfig ruffianConfig = config.getShopConfigMap().get(ruffian.getEventId());
                        if (ruffianConfig == null || ruffianConfig.getType() != eJieShiShopType.Ruffian.getValue()) {
                            continue;
                        }
                        List<Integer> effectParamList = StringUtils.stringToIntegerList(ruffianConfig.getEffect(), "\\|");
                        // 判断下是否能影响到
                        // 计算下影响的受加成的坐标
                        List<Integer> effectPositionList = new ArrayList<>();
                        // 影响的范围
                        int effectRange = effectParamList.get(0);
                        for (int i = -effectRange; i <= effectRange; i++) {
                            int leftRange = ruffian.getPosition() + i * mapWidth - effectRange;
                            int rightRange = ruffian.getPosition() + i * mapWidth + effectRange;
                            for (int j = leftRange; j <= rightRange; j++) {
                                if (j == ruffian.getPosition()) {
                                    continue;
                                }
                                if (!jieShiMap.containsKey(j)) {
                                    // 不存在地图
                                    continue;
                                }
                                effectPositionList.add(j);
                            }
                        }
                        boolean isEffect = false;
                        for (int p : buildData.getPosition()) {
                            if (effectPositionList.contains(p)) {
                                isEffect = true;
                                break;
                            }
                        }
                        if (!isEffect) {
                            continue;
                        }
                        long ruffianAddition = Math.abs(effectParamList.get(1));
                        // 判断收益剩多少
                        ruffianAddition = Math.min(ruffianAddition, buildAddition);
                        buildAddition -= ruffianAddition;
                        long ruffianMoney = BigDecimal.valueOf(Long.parseLong(shopConfig.getMoney())).multiply(BigDecimal.valueOf(buildRoundAdd).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP)).multiply(BigDecimal.valueOf(ruffianAddition)).divide(BigDecimal.valueOf(1000), 0, RoundingMode.UP).longValue();
                        totalRuffianAddition += ruffianAddition;
                        // 减益的都加到泼皮上
                        ruffian.setJiaoZi(ruffian.getJiaoZi() + ruffianMoney);
                    }
                    // 获取收益
                    long addMoney = BigDecimal.valueOf(Long.parseLong(shopConfig.getMoney())).multiply(BigDecimal.valueOf(buildRoundAdd).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP)).multiply(BigDecimal.valueOf(buildAddition)).divide(BigDecimal.valueOf(1000), 0, RoundingMode.UP).longValue();
                    totalMoney += addMoney;
                    flag = true;
                    if (Config.isDebug()) {
                        log.info("【灯火街市】用户id:{},巡游,道路位置:{},商铺id:{},商铺位置:{},总收益加成(含泼皮、自身千分比):{},泼皮减益(千分比):{},获得收益:{}", player.getUserId(), position, buildData.getBuildId(), buildData.getPosition().toString(), buildAddition, totalRuffianAddition, addMoney);
                    }
                    log.info("【街市巡游】用户id:{},步骤5,道路位置:{},商铺id:{},商铺位置:{},总收益加成(含泼皮、自身千分比):{},泼皮减益(千分比):{},获得收益:{},耗时:{} ms ", player.getUserId(), position, buildData.getBuildId(), buildData.getPosition().toString(), buildAddition, totalRuffianAddition, addMoney, System.currentTimeMillis() - start);
                }
            }
            if (flag) {
                JieShiTravelResultData resultData = new JieShiTravelResultData();
                resultData.setPosition(position);
                resultData.setJiaoZi(totalMoney);
                resultData.setReward(PropertyHelper.parsePropertyToString(eventReward));
                resultDataList.add(resultData);
                totalAddJiaoZi += totalMoney;
            }
        }
        // 门客拜访
        List<JieShiTravelVisitData> visitDataList = new ArrayList<>();
        List<Integer> hadVisitShopPosition = new ArrayList<>();
        List<Integer> allPatronsIds = getAllPatronsIds();
        // 打乱下
        Collections.shuffle(allPatronsIds);
        for (int patronsId : allPatronsIds) {
            // 门客拜访
            if (randomHelper.next(0, 1000) < patronConfig.getVisitPro()) {
                // 随机一个商铺
                JieShiMapBuildData buildData = randomGetBuildByType(eJieShiShopType.Store.getValue(), hadVisitShopPosition);
                if (buildData != null) {
                    LightMarketShopConfig shopConfig = config.getShopConfigMap().get(buildData.getBuildId());
                    if (shopConfig == null) {
                        continue;
                    }
                    hadVisitShopPosition.addAll(buildData.getPosition());
                    List<Integer> loadPositions = getLoadPositionByBuild(buildData);
                    // 添加门客拜访
                    JieShiTravelVisitData visitData = new JieShiTravelVisitData();
                    // 随机一个空地
                    visitData.setPosition(loadPositions.get(randomHelper.next(0, loadPositions.size() - 1)));
                    visitData.setShopPosition(buildData.getPosition());
                    visitData.setPatronsId(patronsId);
                    // 产出交子
                    // 获取精进等级
                    UserPatrons userPatrons = player.getModule(PatronsModule.class).getUserPatrons(patronsId);
                    if (userPatrons != null) {
                        int stageLv = userPatrons.getStageLv();
                        // 获取加成
                        List<Integer> visitAddParam = StringUtils.stringToIntegerList(config.getLIGHTMARKET_PARTON_VISIT(), "\\|");
                        long patronsAddition = 0;
                        if (visitAddParam.size() > 0) {
                            patronsAddition += visitAddParam.get(Math.min(stageLv, visitAddParam.size() - 1));
                        }
                        // 这里给的是门客产出的交子
                        long patronJiaoZi = BigDecimal.valueOf(Long.parseLong(shopConfig.getMoney())).multiply(BigDecimal.valueOf(buildRoundAdd).divide(BigDecimal.valueOf(1000), 8, RoundingMode.UP)).multiply(BigDecimal.valueOf(patronsAddition)).divide(BigDecimal.valueOf(1000), 0, RoundingMode.UP).longValue();
                        totalAddJiaoZi += patronJiaoZi;
                        visitData.setJiaoZi(patronJiaoZi);
                        if (Config.isDebug()) {
                            log.info("【灯火街市】用户id:{},门客拜访,道路位置:{},门客id:{},拜访商铺:{},商铺位置:{},产出交子:{}", player.getUserId(), visitData.getPosition(), patronsId, buildData.getBuildId(), buildData.getPosition().toString(), patronJiaoZi);
                        }
                    }
                    visitDataList.add(visitData);
                    log.info("【街市巡游】用户id:{},步骤6,门客拜访,耗时:{} ms ", player.getUserId(), System.currentTimeMillis() - start);
                }
            }
        }
        // 生成事件
        generateEvent();
        log.info("【街市巡游】用户id:{},步骤7,生成事件,耗时:{} ms ", player.getUserId(), System.currentTimeMillis() - start);
        // 增加巡游次数
        userData.setTravelTimes(userData.getTravelTimes() + 1);
        // 增加时辰
        userData.setHour((userData.getHour() + 1) % 12);
        long oldJiaoZi = userData.getJiaoZi();
        // 添加交子
        addJiaoZi(totalAddJiaoZi);
        // 获得奖励
        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.JieShi, eLogMoneyType.JieShiTravelReward);
        // 获得积分奖励
        player.getModule(CurrencyModule.class).addCurrency(new Property(config.getEXCHANGE_SCORE_ITEM_ID(), (long) config.getLIGHTMARKET_SCORE_GET_NUM() * roundCost), eLogMoneyType.JieShi, eLogMoneyType.JieShiTravelReward);
        // 更新下buff
        checkBuff();
        log.info("【街市巡游】用户id:{},步骤8,更新buff,耗时:{} ms ", player.getUserId(), System.currentTimeMillis() - start);
        JieShiProto.JieShiTravelRespMsg.Builder builder = JieShiProto.JieShiTravelRespMsg.newBuilder();
        builder.setRet(0);
        // 巡游过程
        for (JieShiTravelResultData resultData : resultDataList) {
            JieShiProto.JieShiTravelResultTemp.Builder resultTemp = JieShiProto.JieShiTravelResultTemp.newBuilder();
            resultTemp.setPosition(resultData.getPosition());
            resultTemp.setJiaoZi(resultData.getJiaoZi());
            resultTemp.setReward(resultData.getReward());
            builder.addResult(resultTemp);
        }
        // 拜访列表
        for (JieShiTravelVisitData visitData : visitDataList) {
            JieShiProto.JieShiTravelVisitTemp.Builder visitTemp = JieShiProto.JieShiTravelVisitTemp.newBuilder();
            visitTemp.setPosition(visitData.getPosition());
            visitTemp.setJiaoZi(visitData.getJiaoZi());
            visitTemp.addAllShopPosition(visitData.getShopPosition());
            visitTemp.setPatronsId(visitData.getPatronsId());
            builder.addVisitList(visitTemp);
        }
        builder.setUserData(JieShiPb.parseUserDataTemp(userData));
        player.sendPacket(Protocol.U_JIESHI_TRAVEL, builder);
        log.info("【街市巡游】用户id:{},步骤9,回包,耗时:{} ms ", player.getUserId(), System.currentTimeMillis() - start);
        // 体力日志
        AutoLogMgr.add(new LogJieShiEnergy(
                config.getActivityInfo().getActivityId(),
                player.getUserId(),
                3,
                oldEnergy,
                userData.getEnergy() - oldEnergy,
                userData.getEnergy()
        ));
        // 巡游日志
        AutoLogMgr.add(new LogJieShiTravel(
                config.getActivityInfo().getActivityId(),
                player.getUserId(),
                curRound,
                JSON.toJSONString(logEventId),
                JSON.toJSONString(logEventResult),
                oldJiaoZi,
                totalAddJiaoZi,
                userData.getJiaoZi(),
                PropertyHelper.parsePropertyToString(reward)
        ));
        return 0;
    }

    /**
     * 添加buff
     * @param buffId buffId
     */
    public void addBuff(int buffId) {
        if (userData == null) {
            return;
        }
        int curRound = userData.getTravelTimes() + 1;
        List<JieShiBuffData> buffList = userData.getBuffList();
        JieShiConfig config = JieShiMgr.getConfig();
        LightMarketEventConfig eventConfig = config.getEventConfigMap().get(buffId);
        String eventParam = eventConfig.getEventParam();
        // 加buff
        List<Integer> eventParamList = StringUtils.stringToIntegerList(eventParam, "\\|");
        // 判断下有没有buff
        JieShiBuffData buffData = null;
        for (JieShiBuffData data : buffList) {
            if (data.getBuffId() == buffId) {
                buffData = data;
                break;
            }
        }
        if (buffData == null) {
            buffData = new JieShiBuffData();
            buffData.setBuffId(buffId);
            // 下一回合开始生效
            buffData.setStartRound(curRound + 1);
            buffData.setEffectRound(eventParamList.get(0));
            buffList.add(buffData);
        } else {
            // 延长回合数
            buffData.setEffectRound(buffData.getEffectRound() + eventParamList.get(0));
        }
        if (Config.isDebug()) {
            log.info("【灯火街市】用户id:{},添加buff:{},开始生效回合:{},持续回合数:{}", player.getUserId(), buffId, buffData.getStartRound(), buffData.getEffectRound());
        }
        userData.setBuffList(buffList);
    }

    /**
     * buff事件
     */
    private boolean isEventBuff(int eventId) {
        JieShiConfig config = JieShiMgr.getConfig();
        LightMarketEventConfig eventConfig = config.getEventConfigMap().get(eventId);
        return eventConfig.getType() == 3 || eventConfig.getType() == 4;
    }

    public JieShiBuffData getBuffData(int buffId) {
        if (userData == null) {
            return null;
        }
        for (JieShiBuffData buffData : userData.getBuffList()) {
            if (buffData.getBuffId() == buffId) {
                return buffData;
            }
        }
        return null;
    }

    /**
     * 检查下buff有效期
     */
    public void checkBuff() {
        if (userData == null) {
            return;
        }
        // 当前的圈数
        int curRound = userData.getTravelTimes() + 1;
        // 检测下buff生效时间,过期的移除掉
        Iterator<JieShiBuffData> iterator = userData.getBuffList().iterator();
        while (iterator.hasNext()) {
            JieShiBuffData buffData = iterator.next();
            if (curRound >= buffData.getStartRound() + buffData.getEffectRound()) {
                if (Config.isDebug()) {
                    log.info("【灯火街市】用户id:{},buffId:{},已过期", player.getUserId(), buffData.getBuffId());
                }
                iterator.remove();
            }
        }
    }

    /**
     * 获取指定位置上的泼皮
     */
    public JieShiRuffianData getJieShiRuffianDataByPosition(int position) {
        if (userData == null) {
            return null;
        }
        for (JieShiRuffianData ruffianData : userData.getRuffianList()) {
            if (ruffianData.getPosition() == position) {
                return ruffianData;
            }
        }
        return null;
    }

    public JieShiEventData getJieShiEventDataByPosition(int position) {
        if (userData == null) {
            return null;
        }
        for (JieShiEventData eventData : userData.getEventList()) {
            if (eventData.getPosition() == position) {
                return eventData;
            }
        }
        return null;
    }


    /**
     * 获取已拥有的门客列表
     */
    public List<Integer> getAllPatronsIds() {
        List<Integer> list = new ArrayList<>();
        if (userData == null) {
            return list;
        }
        for (JieShiPatronsData patron : userData.getPatronsDataList()) {
            list.add(patron.getPatronsId());
        }
        return list;
    }

    /**
     * 获取建筑相邻的道具位置
     */
    public List<Integer> getLoadPositionByBuild(JieShiMapBuildData buildData) {
        List<Integer> list = new ArrayList<>();
        if (userData == null) {
            return list;
        }
        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null) {
            return list;
        }
        int mapWidth = config.getMapWidth();
        List<Integer> path = config.getJieShiMapPath();
        Map<Integer, Integer> jieShiMap = config.getJieShiMap();
        int[] direction = new int[]{-mapWidth, mapWidth, -1, 1};
        for (Integer position : buildData.getPosition()) {
            for (int dir : direction) {
                int newPosition = position + dir;
                if (!jieShiMap.containsKey(newPosition)) {
                    continue;
                }
                if (path.contains(newPosition)) {
                    list.add(newPosition);
                }
            }
        }
        return list;
    }

    /**
     * 根据类型获取道路边的建筑
     *
     * @param type
     * @param notIncludePosition
     * @return
     */
    public JieShiMapBuildData randomGetBuildByType(int type, List<Integer> notIncludePosition) {
        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null || userData == null) {
            return null;
        }
        List<JieShiMapBuildData> list = new ArrayList<>();
        for (JieShiMapBuildData buildData : userData.getMapBuildList()) {
            LightMarketShopConfig shopConfig = config.getShopConfigMap().get(buildData.getBuildId());
            if (shopConfig == null || shopConfig.getType() != type) {
                continue;
            }
            boolean flag = false;
            for (Integer position : buildData.getPosition()) {
                if (notIncludePosition.contains(position)) {
                    flag = true;
                    break;
                }
            }
            if (flag) {
                continue;
            }
            // 判断是不是在道路边
            if (getLoadPositionByBuild(buildData).size() == 0) {
                continue;
            }
            list.add(buildData);
        }
        if (list.size() == 0) {
            return null;
        }
        return list.get(randomHelper.next(0, list.size() - 1));
    }

    /**
     * 给事件随机个位置
     * @param isRuffian 是否泼皮
     */
    private int randomEventPosition(boolean isRuffian) {
        if (userData == null) {
            return -1;
        }
        // 获取配置
        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null) {
            return -1;
        }
        // 获取下当前已有的事件位置
        Set<Integer> eventPositions = new HashSet<>();
        for (JieShiEventData eventData : userData.getEventList()) {
            eventPositions.add(eventData.getPosition());
        }
        // 泼皮占用的地点
        for (JieShiRuffianData ruffianData : userData.getRuffianList()) {
            eventPositions.add(ruffianData.getPosition());
        }
        // 获取可生成的空地
        List<Integer> list = new ArrayList<>();
        List<Integer> path = config.getJieShiMapPath();
        if (path.size() == 0) {
            return -1;
        }
        // 起点
        int start = path.get(0);

        List<Integer> rascalPosition = new ArrayList<>();
        // 泼皮地点
        List<Integer> rascalPoint = config.getRascalPoint(userData.getTravelTimes() + 1);
        List<Integer> jieShiNpcPosList = config.getJieShiNpcPos();
        for (int i = 0; i < jieShiNpcPosList.size(); i++) {
            if (rascalPoint.contains(i + 1)) {
                rascalPosition.add(jieShiNpcPosList.get(i));
            }
        }
        List<Integer> allPosition;
        if (isRuffian) {
            allPosition = new ArrayList<>(rascalPosition);
        } else {
            allPosition = path.stream().filter(integer -> !rascalPosition.contains(integer)).collect(Collectors.toList());
        }
        for (int position : allPosition) {
            if (!eventPositions.contains(position) && position != start) {
                list.add(position);
            }
        }
        return list.size() > 0 ? list.get(randomHelper.next(0, list.size())) : -1;
    }

    /**
     * 生成事件
     * 泼皮事件和其他事件独立触发
     */
    public void generateEvent() {
        if (userData == null) {
            return;
        }
        // 当前圈数
        int travelTimes = userData.getTravelTimes() + 1;
        // 随机下泼皮
        JieShiConfig config = JieShiMgr.getConfig();
        LightMarketRhythmConfig rhythmConfig = config.getRhythmConfigMap().get(Math.min(travelTimes, config.getRhythmConfigMap().size() - 1));
        if (!"0".equals(rhythmConfig.getEventParam1())) {
            // 获取当前所有的泼皮
            List<Integer> ruffianEventIdList = new ArrayList<>();
            for (JieShiRuffianData ruffianData : userData.getRuffianList()) {
                ruffianEventIdList.add(ruffianData.getEventId());
            }
            // 不为0 则可以生成泼皮
            List<String> list = StringUtils.stringToStringList(rhythmConfig.getEventParam1(), "\\|");
            int eventId = 0;
            // 总权重
            int sumWeight = 0;
            for (String s : list) {
                String[] split = s.split(";");
                int id = Integer.parseInt(split[0]);
                if (ruffianEventIdList.contains(id)) {
                    continue;
                }
                sumWeight += Integer.parseInt(split[1]);
            }
            // 随机一个权重
            int randomWeight = (int) (Math.random() * sumWeight);
            // 当前权重
            int curWeight = 0;
            for (String s : list) {
                String[] split = s.split(";");
                int id = Integer.parseInt(split[0]);
                if (ruffianEventIdList.contains(id)) {
                    continue;
                }
                curWeight += Integer.parseInt(split[1]);
                if (randomWeight < curWeight) {
                    eventId = id;
                    break;
                }
            }
            // 生成泼皮
            genRuffianEvent(eventId);
        }
        // 随机下其他事件
        String eventParam2 = rhythmConfig.getEventParam2();
        // 事件1概率千分比#事件2概率千分比#事件3概率千分比
        String[] split = eventParam2.split("#");
        for (int i = 0; i < split.length; i++) {
            int type = i + 1;
            if (randomHelper.next(0, 1000) < Integer.parseInt(split[i])) {
                int eventId = config.randomGetEventIdByEventType(type);
                genEvent(eventId);
            }
        }
    }

    /**
     * 生成事件
     *
     * @param eventId 事件id
     */
    public void genEvent(int eventId) {
        if (userData == null) {
            return;
        }
        if (eventId <= 0) {
            return;
        }
        int randomEventPosition = randomEventPosition(false);
        if (randomEventPosition == -1) {
            return;
        }
        JieShiEventData eventData = new JieShiEventData();
        eventData.setEventId(eventId);
        eventData.setPosition(randomEventPosition);
        eventData.setGenRound(userData.getTravelTimes() + 1);
        List<JieShiEventData> eventList = userData.getEventList();
        eventList.add(eventData);
        userData.setEventList(eventList);
        if (Config.isDebug()) {
            log.info("【灯火街市】用户id:{},生成特殊事件,生成圈数:{},位置:{},事件id:{}", player.getUserId(), eventData.getGenRound(), randomEventPosition, eventId);
        }
    }

    /**
     * 生成泼皮事件
     */
    public void genRuffianEvent(int eventId) {
        if (userData == null) {
            return;
        }
        if (eventId <= 0) {
            return;
        }
        // 当前圈
        int travelTimes = userData.getTravelTimes() + 1;
        JieShiConfig config = JieShiMgr.getConfig();
        LightMarketRhythmConfig rhythmConfig = config.getRhythmConfigMap().get(Math.min(travelTimes, config.getRhythmConfigMap().size()));
        int randomEventPosition = randomEventPosition(true);
        if (randomEventPosition != -1) {
            // 触发泼皮事件
            JieShiRuffianData ruffianData = new JieShiRuffianData();
            // 随机一个位置
            ruffianData.setPosition(randomEventPosition);
            ruffianData.setEventId(eventId);
            ruffianData.setGenRound(travelTimes);
            // 随机下泼皮名字
            ruffianData.setImageId(randomHelper.next(1, config.getLIGHTMARKET_RASCAL_NAME_NUM() + 1));
            LightMarketShopConfig shopConfig = config.getShopConfigMap().get(eventId);
            // 产出交子加成
            String money = shopConfig.getMoney();
            // 武力加成
            int force = shopConfig.getForce();
            // 生成下武力
            int standardForce = rhythmConfig.getStandardForce();
            ruffianData.setAttack(BigDecimal.valueOf(standardForce).multiply(BigDecimal.valueOf(force)).divide(BigDecimal.valueOf(1000), 0, RoundingMode.UP).longValue());
            // 产出交子
            String standardMoneySpeed = rhythmConfig.getStandardMoneySpeed();
            ruffianData.setJiaoZi(BigDecimal.valueOf(Long.parseLong(standardMoneySpeed)).multiply(BigDecimal.valueOf(Long.parseLong(money))).divide(BigDecimal.valueOf(1000), 0, RoundingMode.UP).longValue());
            List<JieShiRuffianData> ruffianList = userData.getRuffianList();
            ruffianList.add(ruffianData);
            userData.setRuffianList(ruffianList);
            if (Config.isDebug()) {
                log.info("【灯火街市】用户id:{},生成泼皮事件,生成圈数:{},位置:{},事件id:{},交子:{},武力:{}", player.getUserId(), ruffianData.getGenRound(), randomEventPosition, eventId, ruffianData.getJiaoZi(), ruffianData.getAttack());
            }
        }
    }

    /**
     * 随机获取一个门客拜访
     */
    public int randomVisitPatronsId(Set<Integer> visitPatrons) {
        int patronsId = 0;
        List<Integer> list = new ArrayList<>();
        for (JieShiPatronsData patronsData : userData.getPatronsDataList()) {
            if (!visitPatrons.contains(patronsData.getPatronsId())) {
                list.add(patronsData.getPatronsId());
            }
        }
        if (list.size() > 0) {
            patronsId = list.get(randomHelper.next(0, list.size()));
        }
        return patronsId;
    }

    /**
     * 获取建筑加成值
     *
     * @param type 1:交子加成  2:食物加成
     */
    private long getBuildAddition(List<JieShiMapBuildData> buildDataList, JieShiMapBuildData buildData, int type) {
        // 加成千分比
        long addition = 0;
        JieShiConfig config = JieShiMgr.getConfig();

        // 获取建筑
        for (JieShiMapBuildData data : buildDataList) {
            // 自己不处理
            if (data.equals(buildData)) {
                continue;
            }
            addition += getShopAddition(buildData, data.getBuildId(), data.getPosition());
        }
        // 人偶只影响交子加成
        if (type == 1) {
            // 交子人偶加成
            addition += getDollAddition(config.getLIGHTMARKET_DOY_JIAOZI_ITEM_ID());
        }
        // buff加成
        for (JieShiBuffData buffData : userData.getBuffList()) {
            // buff未生效
            if (buffData.getStartRound() > userData.getTravelTimes() + 1) {
                continue;
            }
            // buff已失效
            if (buffData.getStartRound() + buffData.getEffectRound() <= userData.getTravelTimes() + 1) {
                continue;
            }
            int buffId = buffData.getBuffId();
            LightMarketEventConfig eventConfig = config.getEventConfigMap().get(buffId);
            if (type == 1 && eventConfig.getType() != 4) {
                continue;
            }
            if (type == 2 && eventConfig.getType() != 3) {
                continue;
            }
            addition += Integer.parseInt(eventConfig.getEventParam().split("\\|")[1]);
        }
        return addition;
    }


    /**
     * 获取人偶加成
     */
    public long getDollAddition(int dollId) {
        long addition = 0;
        long now = System.currentTimeMillis();
        List<JieShiDollData> dollList = userData.getDollList();
        for (JieShiDollData dollData : dollList) {
            if (dollData.getDollId() != dollId) {
                continue;
            }
            if (dollData.getExpireTime() != 0 && dollData.getExpireTime() < now) {
                // 已过期人偶
                continue;
            }
            GoodsInfo goodsInfo = CommonMgr.getGoodsInfo(dollData.getDollId());
            if (goodsInfo == null) {
                continue;
            }
            addition = goodsInfo.getParamList().get(0).longValue();
        }
        return addition;
    }


    private long getShopAddition(JieShiMapBuildData buildData, int id, List<Integer> positions) {
        JieShiConfig config = JieShiMgr.getConfig();
        if (config == null) {
            return 0;
        }
        int mapWidth = config.getMapWidth();
        Map<Integer, Integer> jieShiMap = config.getJieShiMap();

        // 需要加成的商铺
        LightMarketShopConfig addShopConfig = config.getShopConfigMap().get(buildData.getBuildId());
        LightMarketShopConfig shopConfig = config.getShopConfigMap().get(id);

        if (shopConfig == null) {
            return 0;
        }
        int effectType = shopConfig.getEffectType();
        // -1 无加成
        if (effectType == -1) {
            return 0;
        }
        // 0 以建筑为中心，向外扩散（影响小吃、货铺）
        if (effectType == 0 && addShopConfig.getType() != eJieShiShopType.Snacks.getValue() && addShopConfig.getType() != eJieShiShopType.Store.getValue()) {
            return 0;
        }
        // 1 以建筑为中心，向外扩散（只影响货铺）
        if (effectType == 1 && addShopConfig.getType() != eJieShiShopType.Store.getValue()) {
            return 0;
        }
        List<Integer> effectParamList = StringUtils.stringToIntegerList(shopConfig.getEffect(), "\\|");
        // 计算下影响的受加成的坐标
        // 影响的范围
        int effectRange = effectParamList.get(0);
        // 中心坐标
        for (int position : positions) {
            // 影响范围
            for (int i = -effectRange; i <= effectRange; i++) {
                int leftRange = position + i * mapWidth - effectRange;
                int rightRange = position + i * mapWidth + effectRange;
                for (int j = leftRange; j <= rightRange; j++) {
                    if (j == position) {
                        continue;
                    }
                    if (!jieShiMap.containsKey(j)) {
                        // 不存在地图
                        continue;
                    }
                    if (buildData.getPosition().contains(j)) {
                        // 吃到加成
                        return effectParamList.get(1);
                    }
                }
            }
        }
        return 0;
    }

    /**
     * 获取坐标上的建筑
     */
    private JieShiMapBuildData getMapBuildInPosition(int position) {
        for (JieShiMapBuildData buildData : userData.getMapBuildList()) {
            if (buildData.getPosition().contains(position)) {
                return buildData;
            }
        }
        return null;
    }

    public JieShiUserData getUserData() {
        return userData;
    }
}
